import json
import getopt
import sys
import os
import subprocess
import time


def get_args(argv):
    # 命令行参数解析
    sys_args = {}
    try:
        opts, args = getopt.getopt(
            argv,
            "c:d:p:m:o:e:",
            [
                "sim-config=",
                "driver-config=",
                "param-valid-file=",
                "model-dir=",
                "output-file-path=",
                "entry=",
            ],
        )
    except getopt.GetoptError:
        print(
            "Error: matlabDriver.py -c <config.json> -d <driver.config.json>"
            "-p <param_valid.json> -m <model_dir> -o <output.json file path> -e <entry file name>"
        )
        print(
            "  or: aspenPlusDriver.py --sim-config=<config.json> --driver-config=<driver.config.json>"
            "--param-valid-file=<config.json> --model-dir=<model_dir> --output-file-path=<file path> "
            "--entry=<entry file name>"
        )
        sys.Exit(1)
    for opt, arg in opts:
        if opt in ("-c", "--sim-config"):
            sys_args["simConfig"] = arg
        elif opt in ("-d", "--driver-config"):
            sys_args["driverConfig"] = arg
        elif opt in ["-p", "--param-valid-file"]:
            sys_args["paramValidFile"] = arg
        elif opt in ["-m", "--mode-dir"]:
            sys_args["modelDir"] = arg
        elif opt in ["-o", "--output-file-path"]:
            sys_args["outputFilePath"] = arg
        elif opt in ["-e", "--entry"]:
            sys_args["entry"] = arg
    return sys_args


def writeOutputFile(output_file_path, content):
    if not os.path.isdir(os.path.dirname(output_file_path)):
        os.mkdir(os.path.dirname(output_file_path))
    with open(output_file_path, "w") as file:
        file.write(content)


def run_meta(cmd):
    # 运行meta
    print("simulation start", flush=True)
    global end
    p = subprocess.Popen(
        cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="UTF-8"
    )
    p.communicate()
    end = True


def run(run_config_json_file, driver_path, output_file):
    global end
    with open(driver_path, "r") as file:
        driver_config = json.load(file)
        exe_path = driver_config["config"]["metaExePath"]
    with open(run_config_json_file, "r") as file:
        simulation_config = json.load(file)
    absolute_entry = os.path.join(
        simulation_config["model"]["file"], simulation_config["model"]["entry"])
    work_dir = os.path.dirname(absolute_entry)
    # 更新脚本文件,该脚本实现读取odb文件并导出节点的xyz坐标和位移的数据
    with open("./scripts/demo1_export_odb.py", "r") as file:
        data = file.read()
    data = data.format_map(
        {
            "model_filename": absolute_entry,
            "result_filename": absolute_entry,
            "work_dir": work_dir
        }
    )
    script_path = os.path.join(work_dir, "demo1_export_odb.py")
    with open(script_path, "w") as file:
        file.write(data)
    cmd = f'''{exe_path} -b -exec "script execute {script_path}::main()"'''
    run_meta(cmd)
    while True:
        if end:
            params_value = {
                "success": True,
                "message": "",
                "data": {"simulationResultDir": "", "specifiedParameters": []},
            }
            print("simulation success", flush=True)
            if simulation_config["result"]["uploadRawSimResult"]:
                # 是否需要回传仿真结果文件
                # meta没有参数解析的功能,这个if可以注释掉,将脚本运行的结果直接回传
                params_value["data"]["simulationResultDir"] = work_dir
            if simulation_config["result"]["specifiedLocalPath"]:
                # 是否需要复制仿真结果文件
                cmd = f"""xcopy "{work_dir}" "{simulation_config["result"]["specifiedLocalPath"]}" /s /e /y"""
                os.system(cmd)
            writeOutputFile(output_file, json.dumps(params_value))
            return


if __name__ == "__main__":
    mode = sys.argv[1]
    sysArgs = get_args(sys.argv[2:])
    print(f"mode = {mode},sysArgs = {sysArgs}", flush=True)
    if mode == "parse":
        # 参数解析模式
        print("meta-post not support parse", flush=True)
        output_file = sysArgs.get("outputFilePath")
        writeOutputFile(
            output_file, json.dumps(
                {"success": False, "message": "meta-post not support parse"})
        )
    elif mode == "run":
        # 运行计算模式
        run_config_json_file = sysArgs.get("simConfig")
        with open(run_config_json_file, "r", encoding="utf-8") as file:
            config_content = json.load(file)
        dirPath = os.path.dirname(os.path.join(
            config_content["model"]["file"], config_content["model"]["entry"]))
        fname = os.path.split(config_content["model"]["entry"])[
            1].split(".")[0]
        logPath = os.path.join(dirPath, f"{fname}.out")
        print(f"log path is {logPath}")
        if run_config_json_file is None:
            print("input file is required", flush=True)
            sys.exit(1)
        driver_path = sysArgs.get("driverConfig")
        if driver_path is None:
            driver_path = "./driver.config.json"
        for f in os.listdir(dirPath):
            if f.endswith(".out"):
                os.remove(os.path.join(dirPath, f))
        output_file = sysArgs.get("outputFilePath")
        run(run_config_json_file, driver_path, output_file)
    else:
        print(f"unsupport sub command: ${mode}", flush=True)
        sys.exit(1)